﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using CtpApi.Struct;
using CtpApi.CtpInterface;

using TraderClient.Models;

namespace TraderClient.Logic.TradeCenter
{
    /// <summary>
    /// 交易管理类
    /// </summary>
    public class TradeManager
    {
        /// <summary>
        /// 持仓
        /// </summary>
        private Dictionary<string, Position> MyPosition;

        /// <summary>
        /// CTP交易接口
        /// </summary>
        private TradeApi tdApi;

        /// <summary>
        /// 单例模式实例对象
        /// </summary>
        private static TradeManager instance;

        /// <summary>
        /// 取得交易管理类实例
        /// </summary>
        /// <returns>交易管理类实例</returns>
        public static TradeManager GetInstance()
        {
            if (instance == null)
                instance = new TradeManager();

            return instance;
        }

        /// <summary>
        /// 私有构造函数，防止显示实例化
        /// </summary>
        private TradeManager()
        {
            InitCtp();
        }


        /************************* 交易函数 *************************/

        #region 交易函数

        /// <summary>
        /// 买入开仓
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略</param>
        /// <param name="code">代码</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        public void Buy(MarketType market, string policy, string code, double price, int volume)
        {
            trade(market, policy, code, DirectionType.Buy, price, volume);
        }

        /// <summary>
        /// 卖出开仓
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略</param>
        /// <param name="code">代码</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        public void Sell(MarketType market, string policy, string code, double price, int volume)
        {
            trade(market, policy, code, DirectionType.Sell, price, volume);
        }

        /// <summary>
        /// 平仓
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略</param>
        /// <param name="code">代码</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        public void Close(MarketType market, string policy, string code, double price, int volume)
        { 
            
        }

        /// <summary>
        /// 是否持有仓位
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略名称</param>
        /// <param name="code">代码</param>
        /// <param name="direction">方向</param>
        /// <returns>如果持有仓位则返回True，否则返回False</returns>
        public bool HavePosition(MarketType market, string policy, string code, DirectionType direction)
        {
            string key = getKey(market, policy, code, direction);

            Position position = MyPosition[key];

            if (position != null && position.Volume > 0)
                return true;
            else
                return false;
        }


        /************************* private *************************/

        /// <summary>
        /// 交易指令
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略</param>
        /// <param name="code">代码</param>
        /// <param name="direction">方向</param>
        /// <param name="price">价格</param>
        /// <param name="volume">数量</param>
        private void trade(MarketType market, string policy, string code, DirectionType direction, double price, int volume)
        {
            string key = getKey(market, policy, code, direction);

            if (!MyPosition.ContainsKey(key))
            {
                Position newPosition = new Position();

                newPosition.Market    = market;
                newPosition.Policy    = policy;
                newPosition.Code      = code;
                newPosition.Direction = direction;

                MyPosition[key] = newPosition;
            }

            if (market == MarketType.Futures)
            {
                if( direction == DirectionType.Buy )
                    tdApi.Buy(code, price, volume);
                else
                    tdApi.Sell(code, price, volume);
            }

            System.Media.SystemSounds.Beep.Play();
        }

        /// <summary>
        /// 获取持仓字典的Key
        /// </summary>
        /// <param name="market">市场</param>
        /// <param name="policy">策略名称</param>
        /// <param name="code">代码</param>
        /// <param name="direction">方向</param>
        /// <returns>持仓字典的Key</returns>
        private string getKey(MarketType market, string policy, string code, DirectionType direction)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(market.ToString()).Append("_")
              .Append(policy).Append("_")
              .Append(code).Append("_")
              .Append(direction.ToString());

            return sb.ToString();
        }

        #endregion


        /************************* CTP交易接口事件 *************************/

        #region CTP交易接口事件

        //注册CTP交易接口事件
        private void InitCtp()
        {
            string borkerID = "4030";
            string userID = "80002863";
            string password = "888888";

            string[] frontTd = { @"tcp://asp-sim2-front1.financial-trading-platform.com:26205" };

            tdApi = new TradeApi(borkerID, userID, password, frontTd);

            tdApi.RtnOrder += OnRtnOrder;
            tdApi.RtnTrade += OnRtnTrade;
            tdApi.RtnInstrumentStatus += OnRtnInstrumentStatus;

            tdApi.ErrRtnOrderInsert += OnErrRtnOrderInsert;
            tdApi.ErrRtnOrderAction += OnErrRtnOrderAction;

            tdApi.RspOrderInsert += OnRspOrderInsert;
            tdApi.RspOrderAction += OnRspOrderAction;

            tdApi.RspQryOrder += OnRspQryOrder;
            tdApi.RspQryTrade += OnRspQryTrade;
            tdApi.RspQryTradingAccount += OnRspQryTradingAccount;
            tdApi.RspQryInvestorPosition += OnRspQryInvestorPosition;
            tdApi.RspQryInvestorPositionDetail += OnRspQryInvestorPositionDetail;
        }


        //报单响应
        private void OnRtnOrder(CThostFtdcOrderField pOrder)
        {

        }

        //报单成交通知
        private void OnRtnTrade(CThostFtdcTradeField pTrade)
        {
            Position position = MyPosition[""];

            PositionDetail pd = new PositionDetail();
            pd.Account   = pTrade.InvestorID;
            pd.OpenTime  = DateTime.Parse(pTrade.TradeDate);
            pd.OpenPrice = pTrade.Price;
            pd.Volume    = pTrade.Volume;

            position.Detail.Add(pd);
        }

        //报单录入请求响应
        private void OnRspOrderInsert(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //报单操作请求响应
        private void OnRspOrderAction(CThostFtdcInputOrderActionField pInputOrderAction, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //报单录入错误回报
        private void OnErrRtnOrderInsert(CThostFtdcInputOrderField pInputOrder, CThostFtdcRspInfoField pRspInfo)
        {

        }

        //报单操作错误回报
        private void OnErrRtnOrderAction(CThostFtdcOrderActionField pOrderAction, CThostFtdcRspInfoField pRspInfo)
        {

        }

        //请求查询报单响应
        private void OnRspQryOrder(CThostFtdcOrderField pOrder, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //请求查询成交响应
        private void OnRspQryTrade(CThostFtdcTradeField pTrade, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //查询资金账户响应
        private void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //查询投资者持仓响应
        private void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //查询投资者持仓明细响应
        private void OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField pInvestorPositionDetail, CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
        {

        }

        //合约交易状态通知
        private void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus)
        {

        }

        #endregion
    }
}
